package com.frank.easyexcel.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.metadata.CellData;
import com.frank.easyexcel.model.PersonInExcel;
import com.frank.easyexcel.validate.ExcelHeadValidate;
import com.frank.globalException.domain.EnumError;
import com.frank.globalException.exception.MyException;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author 小石潭记
 * @date 2020/10/7 21:09
 * @Description: 注意：这里不支持spring的注入
 * 如果需要用到 从外面传值进来 在构造器里初始化
 */
@Slf4j
public class ExcelListener extends AnalysisEventListener<PersonInExcel> {

    private static final int EXCEL_COLUMN_SIZE = 4;

    //可以通过实例获取该值
    private List<PersonInExcel> datas;

    // 由于这里不支持spring的注入，所以需要通过构造器传值进来
    private Integer maxLine;

    private boolean errorFlag = false;

    public ExcelListener(Integer maxLine) {
        datas = new ArrayList<>();
        this.maxLine = maxLine;
    }


    @Override
    public void invokeHead(Map<Integer, CellData> headMap, AnalysisContext context) {
        // 列数不对
        if (headMap.size() != EXCEL_COLUMN_SIZE) {
            throw new MyException(EnumError.EXCEL_COLUMN_ERROR);
        }
        // 如果header被修改过的excel直接拒绝
        headMap.entrySet().forEach(x -> {
            if (!ExcelHeadValidate.validateHeader(x.getValue().getStringValue(),
                    x.getValue().getDataFormatString() + x.getValue().getDataFormat())) {
                log.error("{}列有非法修改，请重新下载模板编辑", x.getValue().getStringValue());
                throw new MyException(EnumError.EXCEL_TEMPLATE);
            }
        });

        super.invokeHead(headMap, context);
    }

    public void invoke(PersonInExcel o, AnalysisContext analysisContext) {
        doSomething(o);//根据自己业务做处理, 做一些参数的检验，是否合法之类的
        datas.add(o);//数据存储到list，供批量处理，或后续自己业务逻辑处理。
    }

    private void doSomething(Object object) {
        //1、入库调用接口
    }

    public List<PersonInExcel> getDatas() {
        return datas;
    }

    public void setDatas(List<PersonInExcel> datas) {
        this.datas = datas;
    }

    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        // datas.clear();//解析结束销毁不用的资源
        if (errorFlag) {
            throw new MyException(EnumError.INVALID_PARAMS);
        }
        // todo 上传完成成功，可以处理一些数据库保存等操作
        // todo 将上面的datas的集合存入数据库，这里需要通过构造器注入service，因为listener本类里面不支持依赖注入
    }

    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        int rowIndex = context.readRowHolder().getRowIndex() + 1;
        if (exception instanceof ExcelDataConvertException) {
            ExcelDataConvertException e = (ExcelDataConvertException) exception;
            // 计算列标，todo 有bug，如果列数超过26就会异常，可以修改成26进制A-Z表示更完善
            char columnIndex = (char) ('A' + e.getColumnIndex());
            log.error("第{}行第{}列{}格式有误请检查！", rowIndex, columnIndex, e.getCellData());
            throw new MyException(EnumError.INVALID_PARAMS);
        } else {
            log.error("第{}行格式有误请检查！", rowIndex);
        }
    }
}
